﻿using NewsReader.Helpers;
using NewsReader.Log;
using NewsReader.ViewModels;
using NewsReaderApp.Settings;
using NewsReaderApp.ViewModels;
using NewsReaderApp.Views;
using System;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.ApplicationModel.Background;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace NewsReaderApp
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    sealed partial class App : Application
    {
        private const string DOWNLOAD_FEED_TASK = "Feed Donwload Builder";
        private const string DOWNLOAD_TASK_ENTRY_POINT = "NewsReaderTasks.LoadFeedsTask";

        internal static Task<IBackgroundTaskRegistration> RegisterBackgroundTaskAsync()
        {
            return Task.Factory.StartNew(() =>
            {
                var reg = BackgroundTaskRegistration.AllTasks.Values.FirstOrDefault(t => t.Name == DOWNLOAD_FEED_TASK);
                if (reg != null)
                {
                    reg.Unregister(true);
                }
                return RegisterNewTask() as IBackgroundTaskRegistration;
            });
        }

        private static BackgroundTaskRegistration RegisterNewTask()
        {
            var builder = new BackgroundTaskBuilder();
            builder.Name = DOWNLOAD_FEED_TASK;
            builder.TaskEntryPoint = DOWNLOAD_TASK_ENTRY_POINT;
            // Frequency is controlled through a setting.
            var trigger = new MaintenanceTrigger((uint)SettingsManager.Instance.GetValue<int>(SupportedSettings.RefreshFrequencyMinutes), false);
            builder.SetTrigger(trigger);
            builder.AddCondition(new SystemCondition(SystemConditionType.InternetAvailable));
            builder.AddCondition(new SystemCondition(SystemConditionType.UserPresent));

            return builder.Register();
        }

        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            this.InitializeComponent();
            this.Resuming += OnResuming;
        }

        private void OnResuming(object sender, object e)
        {
            var rootFrame = (Frame)Window.Current.Content;
            if (rootFrame == null)
                return;

            var mainPage = (NewsReaderPage)rootFrame.Content;
            if (mainPage == null)
                return;

            var vm = mainPage.DataContext as FeedViewModel;
            if (vm == null)
            {
                vm = new FeedViewModel();
                mainPage.DataContext = vm;
            }
        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used when the application is launched to open a specific file, to display
        /// search results, and so forth.
        /// </summary>
        /// <param name="args">Details about the launch request and process.</param>
        protected async override void OnLaunched(LaunchActivatedEventArgs args)
        {
            AppSettings.RegisterSettings();

            await RegisterBackgroundTaskAsync();
            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {

                // First time execution, initialize the logger
                EventListener verboseListener = new StorageFileEventListener("VerboseListener");
                verboseListener.EnableEvents(Logger.Log, EventLevel.Verbose);

                Logger.Log.Info("Beginning App");

                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter

                bool nav = rootFrame.Navigate(typeof(MainPage), args.Arguments);
                if (!nav)
                {
                    throw new Exception("Failed to create initial page");
                }
            }
            // Ensure the current window is active
            Window.Current.Activate();
        }
    }
}